﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.Office.Server.Search.Query;

namespace Trentacular.Office.Server.Search.FacetedSearch.Providers
{
    /// <summary>
    /// Abstract class that provides common properties and implementations to most
    /// Facet Provider implementations.
    /// </summary>
    public abstract class BaseFacetProvider : IFacetProvider
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseFacetProvider"/> class.
        /// </summary>
        public BaseFacetProvider()
        {
            this.FacetTable = new Dictionary<string, Facet>();
        }

        /// <summary>
        /// Gets or sets the facet table.
        /// </summary>
        /// <value>The facet table.</value>
        protected Dictionary<string, Facet> FacetTable { get; private set; }

        #region IFacetProvider Members

        /// <summary>
        /// Gets or sets the faceted search context.
        /// </summary>
        /// <value>The faceted search context.</value>
        public FacetedSearchContext FacetedSearchContext { get; set; }

        /// <summary>
        /// Gets or sets the configuration.
        /// </summary>
        /// <value>The configuration.</value>
        public FacetProviderConfiguration Configuration { get; set; }

        /// <summary>
        /// Gets the managed properties that need to be included in the facet query.
        /// </summary>
        /// <value>The managed properties to be included in the facet query.</value>
        public abstract string[] ManagedPropertiesToQuery { get; }

        /// <summary>
        /// Initializes the facet provider before any rows have been iterated.
        /// </summary>
        /// <param name="resultTable">The result table.</param>
        public abstract void Initialize(ResultTable resultTable);

        /// <summary>
        /// Processes a single row of the result table.
        /// </summary>
        /// <param name="resultTable">The result table.</param>
        public abstract void ProcessRow(ResultTable resultTable);

        /// <summary>
        /// Called after all rows have been processed and returns the generated facets.
        /// If there are more facets than the specified MaxFacetsToDisplay, then only
        /// the facets with the highest counts are returned.
        /// </summary>
        /// <returns>A list of all generated facets.</returns>
        public virtual FacetGroup GetFacets()
        {
            return new FacetGroup(
                this.Configuration,
                this.FacetTable.Values.OrderByDescending(f => f.Count)
                    .Take(Configuration.MaxFacetsToDisplay)
                    .ToList()
                );
        }

        #endregion
    }
}
